import logging
from google.appengine.ext import db
from google.appengine.api import memcache
from eutax.robopuzzle.core.database import Action
from eutax.robopuzzle.core.database import Map
from eutax.robopuzzle.core.database import Tile

class ProgramParser:
  
  def __init__(self, programContent):
    self.programContent = programContent
  
  def getStatements(self):
    actionTypes = self._getActionDictionary()
    statements = []
    for statement in self.programContent.split(','):
      actionKey = statement.strip().lower()
      try:
        action = actionTypes[actionKey]
        statements.append(action)
      except KeyError:
        logging.error('Could not find action with key %s' % actionKey)
    return statements

  def _getActionDictionary(self):
    actionTypes = memcache.get('actions')
    if actionTypes is not None:
      return actionTypes
    else:
      actionTypes = {}
      for action in Action.all():
        actionTypes[action.actionKey] = action
      memcache.add('actions', actionTypes, 60)
      return actionTypes

class MapParser:
  def createMap(self, data):
    map = Map()
    map.data = data
    map.data = self._getStorableMapData(map.tiles)
    return map
  
  def getTiles(self, data):
    rawMap = self._getRawMapContent(data)
    tiles = self._createValidMap(rawMap[0], rawMap[1])
    return tiles

  def _getRawMapContent(self, data):
      tileTypes = self._getTileTypes()
      mapData = []
      maxColumns = 0
      for i, line in enumerate(data.split('\n')):
          mapData.append([])
          for j, entry in enumerate(line.split(',')):
              tileData = entry.strip().lower().split()
              tileKey = tileData[0]
              tileElevation = 0
              if (len(tileData) > 1):
                tileElevation = tileData[1]
              try:
                  tileType = tileTypes[tileKey]
                  tile = self._getDefaultTile()
                  tile.tileKey = tileType.tileKey
                  tile.design = tileType.design
                  tile.elevation = int(tileElevation)
                  mapData[i].append(tile)
                  if j > maxColumns:
                      maxColumns = j
              except KeyError:
                  logging.error('Could not find tile with key %s' % tileKey)
      return (mapData, maxColumns)
    
  def _createValidMap(self, rawMap, maxColumns):
    
    lineTuples = []
    for line in rawMap:
      if len(line) < maxColumns:
        for i in xrange(maxColumns - len(line) + 1):
          line.append(self._getDefaultTile())
      lineTuples.append( tuple(line) )
    
    return tuple(lineTuples)
  
  def _getDefaultTile(self):
    tile = Tile()
    tile.tileKey = 'n'
    tile.design = 'normal'
    tile.elevation = 0
    return tile

  def _getTileTypes(self):
    tileTypes = memcache.get('tiles')
    if tileTypes is not None:
      return tileTypes
    else:
      tileTypes = {}
      for tile in Tile.all():
        tileTypes[tile.tileKey] = tile
      memcache.add('tiles', tileTypes, 60)
      return tileTypes
  
  def _getStorableMapData(self, data):
    mapData = []
    for row in data:
      rowList = []
      for tile in row:
        cellString = '%s %i' % (tile.tileKey, tile.elevation)
        rowList.append(cellString)
      rowString = ', '.join(rowList)
      mapData.append(rowString)
    return '\n'.join(mapData)
      
